// import type { HzChartOptions, HzChartGraphOptions, HzChartFallsOptions, HzChartTimeLineOptions } from '../@type.ss'

import img_minus from '../image/ChartIcon_minus.png?url'
import img_plus from '../image/ChartIcon_plus.png?url'
import img_auto from '../image/ChartIcon_auto.png?url'
import * as libs from '../lib'

var roundRect = function (ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number) {
    if (w < 2 * r) r = w / 2;
    if (h < 2 * r) r = h / 2;
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.arcTo(x + w, y, x + w, y + h, r);
    ctx.arcTo(x + w, y + h, x, y + h, r);
    ctx.arcTo(x, y + h, x, y, r);
    ctx.arcTo(x, y, x + w, y, r);
    ctx.closePath();
}

function rotateContext(ctx: CanvasRenderingContext2D, x: number, y: number, degree: number) {
    ctx.translate(x, y);
    ctx.rotate(degree * Math.PI / 180);
    ctx.translate(-x, -y);
}


function runderImage(path: string, callback: Function) {
    let img = new Image();
    img.src = path;
    img.onload = () => {
        callback(img)
    };
}

interface ChartView {
    left: number,
    button: number,
    top: number,
    right: number
}

class CheckButton {
    status: boolean = false;
    top: number = 0;
    left: number = 0;
    height: number = 0;
    width: number = 0;
    ctx?: CanvasRenderingContext2D
    name: string = '';
    color: string = '';
    key: string = '';
    constructor(ctx: CanvasRenderingContext2D, top: number, left: number, width: number, height: number, name: string, color: string, key: string) {
        this.key = key;
        this.ctx = ctx;
        this.top = top;
        this.left = left;
        this.width = width;
        this.height = height;
        this.name = name;
        this.color = color;
        this.renderCheck(ctx, this.status);
    }
    renderCheck(ctx: CanvasRenderingContext2D, isCheck: boolean) {
        this.status = isCheck;
        ctx.clearRect(this.left, this.top, this.width, this.height);
        ctx.textAlign = 'left';
        ctx.fillStyle = isCheck ? this.color : '#aaa'
        ctx.strokeStyle = this.color
        ctx.lineWidth = 1.5;
        roundRect(ctx, this.left + 3, this.top + 3, this.height - 6, this.height - 6, 4);
        ctx.fill()
        ctx.stroke();
        ctx.font = "14px Microsoft YaHei"
        ctx.fillStyle = '#FFFFFF'
        ctx.fillText(this.name, this.left + this.height + 2, this.top + 4);
    }
    check(x: number, y: number, type: string) {
        var CheckAns = x > this.left && x < this.left + this.width && y > this.top && y < this.top + this.height;
        if (type == 'click' && CheckAns) {
            this.click(x, y);
        }
        return CheckAns
    }
    click(x: number, y: number) {
        this.ctx && this.renderCheck(this.ctx, !this.status);
    }
}


class GraphChart {
    Options: HzChartGraphOptions = {
        ValueColor: '#00FF00',
        MaxColor: '#FF0000',
        MinColor: '#0000FF',
        MeanColor: '#00FFFF',
        GatedColor: '#FFFF00',
        LineWidth: 0.2,
        FontColor: '#FFFFFF',
        FontSize: 12,
    }
    private Layout: HTMLCanvasElement = document.createElement('canvas')
    private View: HTMLCanvasElement = document.createElement('canvas')
    private Select: HTMLCanvasElement = document.createElement('canvas')
    private Mark: HTMLCanvasElement = document.createElement('canvas')
    private LCTX?: CanvasRenderingContext2D
    private SCTX?: CanvasRenderingContext2D
    private VCTX?: CanvasRenderingContext2D
    private MCTX?: CanvasRenderingContext2D


    SelectStatus: any = {
        start: 0,
        status: false
    }

    Buttons: CheckButton[] = []
    width: number = 0
    height: number = 0
    MaxNumber: number = 100
    MinNumber: number = -20
    StarNumber: number = 30000000
    EndMunber: number = 3000023424
    span: number = 6835.9375
    renderStart: number = 30000000
    renderEnd: number = 3000023424
    ChartView: ChartView = {
        left: 0,
        button: 0,
        top: 0,
        right: 0
    }
    constructor(Options: HzChartGraphOptions) {
        this.Options.Dom = Options.Dom;
        if (this.Options.Dom) {
            this.LCTX = this.Layout.getContext('2d') as unknown as CanvasRenderingContext2D
            this.VCTX = this.View.getContext('2d') as unknown as CanvasRenderingContext2D
            this.SCTX = this.Select.getContext('2d') as unknown as CanvasRenderingContext2D
            this.MCTX = this.Select.getContext('2d') as unknown as CanvasRenderingContext2D
            this.Options.Dom.appendChild(this.Layout);
            this.Options.Dom.appendChild(this.Mark);
            this.Options.Dom.appendChild(this.Select);
            this.Options.Dom.appendChild(this.View);
            this.resize();
            var Buttons: any = {
                ValueColor: '实时值',
                MaxColor: '最大值',
                MinColor: '最小值',
                MeanColor: '平均值',
                // GatedColor: '门限',
            };
            var index = 0;
            for (const key in Buttons) {
                const element = Buttons[key];
                var button = new CheckButton(this.LCTX, 10, this.ChartView.left + 85 * index, 80, 20, element, (this.Options as any)[key] as string, key);
                this.Buttons.push(button);
                index++
            }
            this.Options.Dom.onmousemove = (e: MouseEvent) => {
                this.CheckMenutton(e.offsetX, e.offsetY, 'move');
                this.SelectStatus.status && this.SCTX && this.renderSelectLine(this.SCTX, e.offsetX);
            }
            this.Options.Dom.onclick = (e: MouseEvent) => {
                this.CheckMenutton(e.offsetX, e.offsetY, 'click');
            }
            this.View.onmousedown = (e: MouseEvent) => {
                e.stopPropagation();
                this.SelectStatus.status = true;
                this.SelectStatus.start = e.offsetX;
            }
            this.View.onmouseup = (e: MouseEvent) => {
                e.stopPropagation();
                this.SelectStatus.status = false;
                this.SCTX && this.renderSelectView(this.SCTX, e.offsetX);
            }
        };
    }
    renderSelectView(cxt: CanvasRenderingContext2D, x: number) {
        cxt.clearRect(0, 0, this.ChartView.right - this.ChartView.left, this.ChartView.button - this.ChartView.top);
        if (this.SelectStatus.start < x) {
            var width = this.ChartView.right - this.ChartView.left;
            var unit = width / (this.renderEnd - this.renderStart);
            var _startCache = this.renderStart
            this.renderStart = this.SelectStatus.start / unit + _startCache;
            this.renderEnd = x / unit + _startCache;
            this.renderLayout();
        } else {
            this.renderStart = this.StarNumber;
            this.renderEnd = this.EndMunber;
            this.renderLayout();
        }
    }
    renderSelectLine(cxt: CanvasRenderingContext2D, x: number) {
        cxt.clearRect(0, 0, this.ChartView.right - this.ChartView.left, this.ChartView.button - this.ChartView.top);
        cxt.lineWidth = 1;
        cxt.strokeStyle = 'green';
        cxt.beginPath();
        cxt.setLineDash([3]);
        cxt.moveTo(this.SelectStatus.start, 0.5);
        cxt.lineTo(x, 0.5);
        cxt.lineTo(x, this.ChartView.button - this.ChartView.top - 0.5);
        cxt.lineTo(this.SelectStatus.start, this.ChartView.button - this.ChartView.top - 0.5);
        cxt.lineTo(this.SelectStatus.start, 0.5);
        cxt.stroke();
    }
    renderBGStyle(canvas: HTMLCanvasElement) {
        canvas.style.width = this.width + 'px';
        canvas.style.height = this.height + 'px';
        canvas.width = this.width;
        canvas.height = this.height;
        canvas.style.position = 'absolute';
        canvas.style.top = '0px';
        canvas.style.left = '0px';
    }
    renderChartStyle(canvas: HTMLCanvasElement) {
        const { left, button, top, right } = this.ChartView;
        canvas.style.width = right - left + 'px';
        canvas.style.height = button - top + 'px';
        canvas.width = right - left;
        canvas.height = button - top;
        canvas.style.position = 'absolute';
        canvas.style.top = top + 'px';
        canvas.style.left = left + 'px';
    }
    ChangeYNumber(i: number) {
        switch (i) {
            case 0:
                var _v = this.MaxNumber - 20;
                if (_v >= 20) this.MaxNumber = _v;
                this.renderLayout();
                break;
            case 1:
                this.MaxNumber += 20;
                this.renderLayout();
                break;
            case 2:
                this.MaxNumber = 100;
                this.MinNumber = -20;
                this.renderLayout();
                break;
            case 3:
                var _v = this.MinNumber + 20;
                if (_v < 0) this.MinNumber = _v;
                this.renderLayout();
                break;
            case 4:
                this.MinNumber -= 20;
                this.renderLayout();
                break;
        }
    }
    ChangeButtonCursor(type: boolean) {
        this.Options.Dom && (this.Options.Dom.style.cursor = type ? 'pointer' : 'auto')
    }
    CheckMenutton(x: number, y: number, type: string) {
        const { button, top } = this.ChartView;
        var buttonPosition: Array<number> = [top, top + 30, top + 60, button - 50, button - 20];
        var buttonLeft = this.width - 25;

        var onButton = false
        for (let i = 0; i < this.Buttons.length; i++) {
            const element = this.Buttons[i];
            if (element.check(x, y, type)) {
                this.ChangeButtonCursor(true);
                onButton = true;
                break
            }
        }
        if (onButton) return;
        this.ChangeButtonCursor(false);
        if (x > buttonLeft && x < buttonLeft + 20) {
            for (let i = 0; i < buttonPosition.length; i++) {
                const v = buttonPosition[i];
                if (y > v && y < v + 20) {
                    if (type == 'click') {
                        this.ChangeYNumber(i);
                        this.ChangeButtonCursor(true);
                    } if (type == 'move') {
                        this.ChangeButtonCursor(true);
                    }
                    break;
                }
            }
        }
    }
    resize() {
        this.Options.Dom && (this.Options.Dom.style.position = 'relative');
        this.width = this.Options.Dom?.clientWidth || 0;
        this.height = this.Options.Dom?.clientHeight || 0;
        const left = 50;
        const button = this.height - 30;
        const top = 40;
        const right = this.width - 60;
        this.ChartView = { left, button, top, right };
        this.Layout && this.renderBGStyle(this.Layout);
        this.View && this.renderChartStyle(this.View);
        this.Select && this.renderChartStyle(this.Select);
        this.Mark && this.renderChartStyle(this.Mark);

        // this.LCTX && (this.LCTX.fillStyle = '#DD0000')
        // this.LCTX?.fillRect(0, 0, this.width, this.height)
        this.renderStart = this.StarNumber;
        this.renderEnd = this.EndMunber;
        runderImage(img_minus, (img: any) => {
            this.LCTX?.drawImage(img, this.width - 25, top, 20, 20)
            this.LCTX?.drawImage(img, this.width - 25, button - 50, 20, 20)
        });
        runderImage(img_plus, (img: any) => {
            this.LCTX?.drawImage(img, this.width - 25, top + 30, 20, 20)
            this.LCTX?.drawImage(img, this.width - 25, button - 20, 20, 20)
        });
        runderImage(img_auto, (img: any) => {
            this.LCTX?.drawImage(img, this.width - 25, top + 60, 20, 20)
        });
        this.renderLayout();
    }
    renderLayout() {
        console.time('边框渲染');
        const { left, button, top, right } = this.ChartView;
        // Y 轴 最大值 最小值
        const MaxNumber: number = this.MaxNumber;
        const MinNumber: number = this.MinNumber;
        // Y 轴分割单位
        const Unit: number = 20;
        // Y 轴数据区间计算阈值
        const AllCount: number = MaxNumber - MinNumber;
        // 单位值显示高度
        const lineLength = parseInt((AllCount / Unit) as unknown as string);
        // 单位高度
        const UnitHeight: number = (button - top) / lineLength;
        // X 轴起始值
        const start: number = this.renderStart;
        const end: number = this.renderEnd;
        // X 轴分割次数

        // X 轴起始值
        const XlineAllNumber: number = end - start;
        let XCount: number = 10;

        var _Content = Math.ceil(XlineAllNumber / this.span)
        if (_Content < 3) {
            XCount = 3;
        } else if (_Content < 10) {
            XCount = _Content;
        }

        // X 轴 单位数量
        const XlineUnit: number = XlineAllNumber / XCount;
        // X 轴 单位宽度
        const UnitWidth: number = (right - left) / XCount;



        if (this.LCTX) {
            this.LCTX.clearRect(0, top - 3, this.width - 30, this.height);
            // 渲染竖向单位
            rotateContext(this.LCTX, this.width / 2, this.height / 2, -90)
            this.LCTX.fillStyle = this.Options.FontColor || '#FFF'
            this.LCTX.textBaseline = 'middle';
            this.LCTX.textAlign = 'center';
            this.LCTX.fillText('dBμV', this.width / 2, -(this.width / 2 - this.height / 2) + 15)
            this.LCTX.font = "10px Microsoft YaHei"
            rotateContext(this.LCTX, this.width / 2, this.height / 2, 90)
            // 渲染X轴文字
            this.LCTX.fillStyle = this.Options.FontColor || '#FFF'
            this.LCTX.beginPath();
            for (let i = 0; i < lineLength + 1; i++) {
                this.LCTX.moveTo(left, button - i * UnitHeight);
                this.LCTX.lineTo(right, button - i * UnitHeight);
                // Y轴 与 Y轴文字
                if (i == 0) {
                    this.LCTX.textBaseline = 'bottom';
                } else if (i == lineLength) {
                    this.LCTX.textBaseline = 'top';
                } else {
                    this.LCTX.textBaseline = 'middle';
                }
                this.LCTX.textAlign = 'right';
                this.LCTX.fillText(MinNumber + i * Unit + '', left - 7, button - i * UnitHeight);
                this.LCTX.textAlign = 'left';
                this.LCTX.fillText(MinNumber + i * Unit + '', right + 7, button - i * UnitHeight);
            }
            this.LCTX.textBaseline = 'top';
            this.LCTX.textAlign = 'center';
            for (let i = 0; i < XCount + 1; i++) {
                // X轴 与 X轴文字
                this.LCTX.fillText(libs.bytesToSize(start + i * XlineUnit, 13 - XCount) + 'Hz', left + UnitWidth * i, button + 5);
                this.LCTX.moveTo(left + i * UnitWidth, top);
                this.LCTX.lineTo(left + i * UnitWidth, button);
            }
            this.LCTX.lineWidth = this.Options.LineWidth || 1;
            this.LCTX.strokeStyle = '#FFFFFF';
            this.LCTX.closePath();
            this.LCTX.stroke();
            console.timeEnd('边框渲染');
        }
    }
}

export {
    GraphChart
}